package adventuregame;

import java.util.ArrayList;

/**
 * Contains the game menu, and handles the actions available to the player.
 * @author Jesper & Simon
 */
public class Menu {

	String[] menuLinks = {
		"Look around", "Show inventory", "Pick up", "Drop down", "Move"
	};
	Console console = new Console();
	ArrayList<Room> roomList = null;
	Person gamer = null;
	boolean running = true;

	/**
	 * Initializes menu
	 * @param rl ArrayList<Room>
	 * @param g Person
	 */
	public Menu(ArrayList<Room> rl, Person g) {
		roomList = rl;
		gamer = g;
		running = true;
	}

	/**
	 * Prints menu and calls listLinks and chooseAction.
	 */
	public void show() {
		console.println("[Menu]");
		listLinks();
		console.println("[exit]Quit");
		chooseAction();
	}

	/**
	 * Prints out the actual menu with linebreaks.
	 */
	private void listLinks() {
		for (int i = 0; i <= menuLinks.length - 1; i++) {
			console.println("[" + i + "]" + menuLinks[i]);
		}
	}

	/**
	 * Outputs choose action and listens for input.
	 * If the input is an int it calls the corresponding action.
	 * If the input isnt an int, it prints action not recognized,
	 * and shows the menu again.
	 */
	public void chooseAction() {
		console.println("Choose action: ");
		String input = console.in();
		if (isIntNumber(input)) {
			int x = Integer.parseInt(input);
			goTo(x);
		} else if(input.equals("exit")) {
			running = false;		
		} else {
			console.println("Action not recognized");
			show();
		}
	}

	/**
	 * Calls action based upon the user made menu selection.
	 * If the selection isnt valid, printout not an option,
	 * and show the menu.
	 * @param inInt Input
	 */
	private void goTo(int inInt) {
		switch (inInt) {
			case 0:
				lookAroundLink();
				break;
			case 1:
				showInventoryLink();
				break;
			case 2:
				actionLink("pickup");
				break;
			case 3:
				actionLink("drop");
				break;
			case 4:
				actionLink("move");
				break;
			default:
				console.println("Not an option");
				show();
				break;
		}
	}

	/**
	 * Calls lookAround on currentRoom.
	 */
	private void lookAroundLink() {
		currentRoom().lookAround();
	}

	/**
	 * Print out the inventory of the gamer.
	 */
	private void showInventoryLink() {
		console.println("Current inventory: " + gamer.getInventory(false));
	}

	/**
	 * Handles pickup, drop and move functions.
	 * Show option menu of given action type.
	 * Checks if the input is valid and if input equals exit.
	 * @param actionType String "move", "drop", or "pickup".
	 */
	private void actionLink(String actionType) {
		console.println(menuList(actionType));
		console.println("[exit] Cancel");
		console.println("Choose action: ");
		String input = console.in();
		if (isIntNumber(input)) {
			int x = Integer.parseInt(input);
			doAction(actionType, x);
		} else {
			if (input.equals("exit")) {
				show();
			} else {
				console.println("Action not reconized");
				show();
			}
		}
	}

	/**
	 * Returns options.
	 * @param actionType String "move", "drop", or "pickup".
	 * @return String
	 */
	private String menuList(String actionType) {
		if (actionType.equals("move")) {
			return "Where to: \n" + currentRoom().getNeighbours(true);
		} else if (actionType.equals("drop")) {
			return "Which item: \n" + gamer.getInventory(true);
		} else if (actionType.equals("pickup")) {
			return "Which item: \n" + currentRoom().getThings(true);
		}
		return "";
	}

	/**
	 * Calls the action depending on what option is choosen.
	 * @param actionType String "move", "drop", or "pickup".
	 * @param x int
	 */
	private void doAction(String actionType, int x) {
		if (actionType.equals("move")) {
			moveTo(x);
		} else if (actionType.equals("drop")) {
			drop(x);
		} else if (actionType.equals("pickup")) {
			pickup(x);
		}
	}

	/**
	 * Adds choosen item to the gamers inventory,
	 * and removes item from current room.
	 * @param inInt int Item number in optionlist.
	 */
	private void pickup(int inInt) {
		gamer.addToInventory(currentRoom().getThingAt(inInt));
		currentRoom().removeThingAt(inInt);
	}

	/**
	 * Adds choosen item to the current room,
	 * and removes it fromt he gamers inventory.
	 * @param inInt int Item number in optionlist.
	 */
	private void drop(int inInt) {
		currentRoom().addThing(gamer.getThingAt(inInt));
		gamer.removeThingAt(inInt);

	}

	/**
	 * Sets the players location to the one selected from the menu.
	 * @param inInt int Item number in optionlist.
	 */
	private void moveTo(int inInt) {
		gamer.setLocation(currentRoom().getNeighbourAt(inInt));
	}

	/**
	 * Check if input is an int, otherwise catch exception.
	 * @param num String input
	 * @return boolean True if input is an int.
	 */
	public boolean isIntNumber(String num) {

		try {
			Integer.parseInt(num);
		} catch (NumberFormatException nfe) {
			return false;
		}
		return true;

	}

	/**
	 * Returns the players current room.
	 * @return Room object
	 */
	private Room currentRoom() {
		int max = roomList.size();
		for (int i = 0; i < max; i++) {
			if (roomList.get(i).toString().equals(gamer.getLocation())) {
				return roomList.get(i);
			}
		}
		return roomList.get(0);
	}
}
